#pragma once

#include <math.h>
#include <iostream>

using namespace std;

class Vector3f {
public:
    union {
        struct {
            float x, y, z;
        };
        float e[3];
    };

    /* Constructors.
     */

    //Nothing.
    Vector3f();

    Vector3f(float x, float y, float z);
    
    /* Math, non-operator.
     */

    float magnitude() const;
    float magnitude2d() const;

    //Normalizes this vector. Returns the magnitude of this vector.
    float normalize();

    //Normalizes the x and y components.
    float normalize2d();

    //Gets the slope of this vector.
    float getSlope();

    //Rotates the vector counterclockwise about the z axis.
    void rotateLeft(float angle);

    //Rotates the vector about vector ^ z.
    void rotateUp(float angle);

    //Gets a normalized copy of this vector.
    Vector3f getNormalized() const;

    /* Unary operators.
     */
    Vector3f operator-() const;
    float operator[](int i) const;
    
    /* Binary operators with self.
     */
    Vector3f operator+(const Vector3f& v) const;
    void operator+=(const Vector3f& v);
    Vector3f operator-(const Vector3f& v) const;
    void operator-=(const Vector3f& v);
    
    //Dot product.
    float operator*(const Vector3f& v) const;

    //Cross product.
    Vector3f operator^(const Vector3f& v) const;
    void operator^=(const Vector3f& v);

    /* Binary operators with floats.
     */
    friend Vector3f operator*(const Vector3f& v, float f);
    friend Vector3f operator*(float f, const Vector3f& v);
    friend Vector3f operator/(const Vector3f& v, float f);
    friend Vector3f operator/(float f, const Vector3f& v);

    void operator*=(float f);
    void operator/=(float f);

    /* Streams.
     */
    friend ostream& operator<<(ostream& os, Vector3f& v);
    friend istream& operator>>(istream& is, Vector3f& v);

    /* Other. */
    bool timeInRect(float& minT, float& maxT, float dirX, float dirY, float minX, float maxX, float minY, float maxY) const;
};
